//package com.yupi.springbootinit.messagecenter;
//
//import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
//import com.fasterxml.jackson.databind.JsonNode;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import com.yupi.springbootinit.config.RabbitMqConfig;
//import com.yupi.springbootinit.mapper.OutboxEventMapper;
//import com.yupi.springbootinit.model.entity.OutboxEvent;
//import com.yupi.springbootinit.mq.EventEnvelope;
//import jakarta.annotation.Resource;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.amqp.rabbit.core.RabbitTemplate;
//import org.springframework.stereotype.Service;
//
//import java.util.Date;
//import java.util.List;
//
//@Service
//@Slf4j
//public class RabbitOutboxPublisher {
//
//    @Resource
//    private OutboxEventMapper outboxEventMapper;
//
//    @Resource
//    private RabbitTemplate rabbitTemplate;
//
//    @Resource
//    private ObjectMapper objectMapper;
//
//    /**
//     * 发布一批待发送事件，返回成功条数
//     */
//    public int publishPendingBatch(int batchSize) {
//        Date now = new Date();
//        QueryWrapper<OutboxEvent> qw = new QueryWrapper<OutboxEvent>()
//                .eq("status", "PENDING")
//                .and(w -> w.isNull("next_retry_at").or().le("next_retry_at", now))
//                .orderByAsc("id")
//                .last("limit " + Math.max(1, batchSize));
//        List<OutboxEvent> list = outboxEventMapper.selectList(qw);
//        int ok = 0;
//        for (OutboxEvent e : list) {
//            try {
//                JsonNode payloadNode = objectMapper.readTree(e.getPayload());
//                Integer delayMs = null;
//                if (payloadNode.has("delayMs") && payloadNode.get("delayMs").canConvertToInt()) {
//                    delayMs = payloadNode.get("delayMs").asInt();
//                }
//                Object payloadObj = objectMapper.treeToValue(payloadNode, Object.class);
//
//                EventEnvelope envelope = new EventEnvelope(
//                        e.getEventId(),
//                        e.getEventType(),
//                        System.currentTimeMillis(),
//                        e.getRoutingKey(),
//                        payloadObj
//                );
//
//                if (delayMs != null && delayMs > 0) {
//                    final int d = Math.min(delayMs, Integer.MAX_VALUE);
//                    rabbitTemplate.convertAndSend(
//                            RabbitMqConfig.EXCHANGE_DELAYED,
//                            e.getRoutingKey(),
//                            envelope,
//                            m -> {
//                                m.getMessageProperties().setHeader("x-delay", d);
//                                return m;
//                            }
//                    );
//                } else {
//                    rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_DELAYED, e.getRoutingKey(), envelope);
//                }
//
//                OutboxEvent up = new OutboxEvent();
//                up.setId(e.getId());
//                up.setStatus("SENT");
//                up.setNextRetryAt(null);
//                up.setRetryCount(e.getRetryCount());
//                up.setUpdatedAt(new Date());
//                outboxEventMapper.updateById(up);
//                ok++;
//            } catch (Exception ex) {
//                int nextCount = (e.getRetryCount() == null ? 0 : e.getRetryCount()) + 1;
//                long backoffMillis = Math.min(60 * 60_000L, (long) Math.pow(2, Math.min(nextCount, 5)) * 60_000L);
//                Date next = new Date(System.currentTimeMillis() + backoffMillis);
//
//                OutboxEvent up = new OutboxEvent();
//                up.setId(e.getId());
//                up.setRetryCount(nextCount);
//                up.setStatus("PENDING");
//                up.setNextRetryAt(next);
//                up.setUpdatedAt(new Date());
//                outboxEventMapper.updateById(up);
//
//                log.warn("Publish outbox failed id={}, rk={}, will retry at {}", e.getId(), e.getRoutingKey(), next, ex);
//            }
//        }
//        if (ok > 0) {
//            log.info("Outbox published count={}", ok);
//        }
//        return ok;
//    }
//}